package com.xrui.hbase;

import java.io.Closeable;
import java.util.Iterator;

/**
 * <p>Retrieves pages of values from a column in a table.</p>
 *
 * <p> Pager is useful when requesting a large number of values from a column.
 * The page size is an upper limit to the number of cells retrieved from the region servers
 * at a time, to bound the amount of memory consumed on the client machine.</p>
 * To create a {@link Pager}, call {@link RowData#getPager(String)} or
 * {@link RowData#getPager(String, String)} on a {@link RowData} constructed with paging
 * enabled:
 * <pre>
 *     final TableReader reader = ...
 *     final EntityId entityId = ...
 *     final RowData row = reader.create(entityId, dataRequest);
 *     final Pager pager = row.getPager("info", "name");
 *     try  {
 *       while(pager.hasNext()) {
 *         final RowData page = pager.next();
 *         // Use: page.getValues("info", "name")
 *         // ...
 *       }
 *     } finally {
 *       // Always close pagers:
 *       pager.close();
 *     }
 * </pre>
 * Notes:
 * <ul>
 * <li> The page size in an upper bound to the number of cells retrieved in a page.
 * Concretely, a page of cells returned by {@link Pager#next()} or
 * {@link Pager#next(int)} may contain less cells than the page size,
 * even if there are more pages coming.
 * In particular, there may be empty pages even when more pages follow.
 * Use {@link Pager#hasNext()} to determine if more pages follow.
 * </li>
 * <li> When paging over a map-type family, retrieved pages only contain the qualifiers
 * in the family, and no cell content.
 * You may retrieve the cell content with a create request with the qualifiers from the pager.
 * If you need to retrieve many versions for all these qualifier, you may combine the
 * map-family pager with per-qualifier pagers.
 * </li>
 * </ul>
 *
 */
public interface Pager extends Iterator<RowData>, Closeable {
    /**
     * Fetches the next page of cells from the table using the configured page size.
     * <p>
     * <ul>
     * <li> The page size is an upper bound to the number of cells retrieved from the table. </li>
     * <li> The page may contain fewer cells than the specified page size.
     * In particular, the page can sometimes be empty, even though more pages follow.
     * Use {@link Pager#hasNext()} to determine if more pages follow. </li>
     * </ul>
     *
     * @return the next page of cells as a {@link RowData}.
     * Never null, but potentially empty.
     */
    RowData next();

    /**
     * Fetches the next page of cells from the table using the specified page size.
     * <p>
     * <ul>
     * <li> The page size is an upper bound to the number of cells retrieved from the table. </li>
     * <li> The page may contain less cells than the specified page size.
     * In particular, the page can sometimes be empty, even though more pages follow.
     * Use {@link Pager#hasNext()} to determine if more pages follow.</li>
     * </ul>
     *
     * @param pageSize The maximum number of cells to retrieve for this page.
     * @return the next page of data as a {@link RowData}.
     * Never null, but potentially empty.
     */
    RowData next(int pageSize);

    /**
     * Throws {@link UnsupportedOperationException}.
     * <p>
     * <p> Pagers do not support remove(). </p>.
     */
    void remove();
}
